<?
require "include/benc.php";
require "include/bittorrent.php";
dbconn(); 
loggedinorreturn();

ini_set("upload_max_filesize",$max_torrent_size);

//if (get_user_class() < UC_UPLOADER)
//	error("Permission denied.");

function trim_ml(&$nfo, $extras = false)
{
	$lines = array();
	foreach (explode("\n", $nfo) as $line)
		$lines[] = trim($line, "\x00..\x1F.,-+=\t ~");
	$nfo = implode("\n", $lines);
}

function trim_regex($pattern, $replacement, $subject)
{
	trim_ml($subject);
	return preg_replace($pattern, $replacement, $subject);
}

function strip(&$nfo)
{
	$nfo = trim_regex('/[^\\x20-\\x7e\\x0a\\x0d]/', '', $nfo);
	$nfo = trim_regex('/ +/', ' ', $nfo);
	$nfo = trim_regex("/\n[-\s]+\n/", "\n\n", $nfo);
	$nfo = trim_regex("/\n[a-zA-Z][ ~]+[a-zA-Z]\n/", '', $nfo);
	$nfo = trim_regex("/\n[A-Z] ?~+/i", "\n", $nfo);
	$nfo = trim_regex("/~+ ?[A-Z]\n/i", "\n", $nfo);
	$nfo = trim_regex('/([^\s.])[\s.:]+:+[\s.:]+([^\s.])/', '$1: $2', $nfo);
	$nfo = trim_regex("/\s+\[(.+)\]/", ' [$1]', $nfo);
	$nfo = trim_regex("/\n\n\n+/", "\n\n", $nfo);
	$nfo = trim_regex("/\\[ \\] [^[\n]+/", '', $nfo);
	$nfo = str_replace("[ ]\n", "\n", $nfo);
	$nfo = trim_regex("/(: \[[^\]]\] [^\n]+)\n\n/", "\$1\n", $nfo);
	$nfo = trim_regex("/([^\n]+:[^\n]+)\n\n([^\n]+:[^\n]+)/", "$1\n$2", $nfo);
	$nfo = trim_regex("/ \[x\]/i", ',', $nfo);
	$nfo = trim_regex("/ \[(\d+)\]/", ', $1', $nfo);
	$nfo = str_replace(':,', ':', $nfo);
	$nfo = trim_regex("/\[ ([^\]]+) \]/", '$1', $nfo);
	$nfo = trim_regex("/\n\n\n+/", "\n\n", $nfo);
	trim_ml($nfo, $extra);
	$nfo = trim($nfo);
}

function dict_get($d, $s) {
	if ($d["type"] != "dictionary")
		error("Not a dictionary.");
	$a = explode(":", $s);
	$dd = $d["value"];
	$ret = array();
	$t='';
	foreach ($a as $k) {
		unset($t);
		if (preg_match('/^(.*)\((.*)\)$/', $k, $m)) {
			$k = $m[1];
			$t = $m[2];
		}
		if (!isset($dd[$k]))
			error("Dictionary is missing key(s).");
		if (isset($t)) {
			if ($dd[$k]["type"] != $t)
				error("Invalid dictionary entry type.");
			$ret[] = $dd[$k]["value"];
		}
		else
			$ret[] = $dd[$k];
	}
	return $ret;
}

$f = $_FILES["file"];
$nfofile = $_FILES['nfo'];
$userdescr = $_POST["descr"];
$catid = (int)$_POST["type"];

$fname = unesc($f["name"]);
$nfofilename = $nfofile['tmp_name'];
$tmpname = $f["tmp_name"];
$redown = "";

if (!$fname)
	error("No torrent file selected!");

if ($nfofile['size'] > 65535)
	error("NFO is too big! The max is 65,535 bytes.");

if (!$userdescr && (!$nfofile['name'] || !$nfofile['size'] || !is_uploaded_file($nfofilename)))
	error("You must enter a description or NFO!");

if (!is_valid_id($catid))
	error("You must select a category to put the torrent in!");
	
if (!preg_match('/^[^\0-\x1f:\\\\\/?*\xff#<>|]+$/si', $fname))
	error("Invalid torrent file name!");
if (!preg_match('/^(.+)\.torrent$/si', $fname, $matches))
	error("Invalid torrent file name (not a .torrent).");
$shortfname = $torrent = $matches[1];

if ($_POST["name"])
	$torrent = unesc($_POST["name"]);

if (!is_uploaded_file($tmpname))
	error("The torrent file upload failed.");
if (!filesize($tmpname))
	error("The torrent file is empty!");

$dict = bdec_file($tmpname, $max_torrent_size);
if (!isset($dict))
	error("What the hell did you upload? This is not a bencoded torrent file!");

list($info) = dict_get($dict, "info");
list($dname, $plen, $pieces) = dict_get($info, "name(string):piece length(integer):pieces(string)");

if (strlen($pieces) % 20 != 0)
	error("Invalid torrent pieces.");

$filelist = array();

if (isset($dict['value']['info']['value']['length']))
{
	list($totallen) = dict_get($info, "length(integer)");
	$filelist[] = array($dname, $totallen);
	$type = "single";
}
else
{
	list($flist) = dict_get($info, "files(list)");
	if (!isset($flist))
		error("Torrent missing both length and files.");
	if (!count($flist))
		error("No files in torrent.");
	$totallen = 0;
	foreach ($flist as $fn)
	{
		list($ll, $ff) = dict_get($fn, "length(integer):path(list)");
		$totallen += $ll;
		$ffa = array();
		foreach ($ff as $ffe)
		{
			if ($ffe["type"] != "string")
				error("Invalid entry in dictionary.");
			$ffa[] = $ffe["value"];
		}
		if (!count($ffa))
			error("No directory structure or file name.");
		$ffe = implode("/", $ffa);
		$filelist[] = array($ffe, $ll);
	}
	$type = "multi";
}

foreach ($filelist as $file)
	if (eregi("\.rar$", $file[0]))
		error("Rar files are not allowed. Please extract the files before creating the torrent.");

$originalinfohash = pack("H*", sha1($info["string"]));

$dict['value']['announce']=bdec(benc_str($announce_urls[0]));  // change announce url to local
$dict['value']['info']['value']['private']=bdec('i1e');  // add private tracker flag
$dict['value']['info']['value']['rtsalt']=bdec('i'.mt_rand(0,100000).'e'); // add random data for unique infohash
unset($dict['value']['announce-list']); // remove multi-tracker capability
unset($dict['value']['url-list']); // remove web seed capability
unset($dict['value']['nodes']); // remove cached peers (Bitcomet & Azareus)
$dict=bdec(benc($dict)); // double up on the becoding solves the occassional misgenerated infohash
list($info) = dict_get($dict, "info");
$infohash = pack("H*", sha1($info["string"]));

if ($originalinfohash != $infohash)
$redown = "&redownload=1";

// Replace punctuation characters with spaces

$torrent = str_replace("_", " ", $torrent);

$nfo = str_replace("\x0d\x0d\x0a", "\x0d\x0a", @file_get_contents($nfofilename));

if ($nfo)
{
	$descr = $nfo;
	strip($descr);
	if ($userdescr)
		$descr .= "\r\n\r\n" . $userdescr;
}
else
	$descr = $userdescr;

$time = get_date_time();

$searchtext = searchfield("$shortfname $dname $torrent");

$ret = query("INSERT INTO torrents (search_text, filename, owner, visible, info_hash, name, size, numfiles, type, descr, ori_descr, category, save_as, added, last_action, nfo) VALUES (" . sqlesc($searchtext) . ", " . sqlesc($fname) . ", $CURUSER[id], 'no', " . sqlesc($infohash) . ", " . sqlesc($torrent) . ", " . sqlesc($totallen) . ", " . sqlesc(count($filelist)) . ", " . sqlesc($type) . ", " . sqlesc($descr) . ", " . sqlesc($descr) . ", $catid, " . sqlesc($dname) . ", '$time', '$time', " . sqlesc($nfo) . ")");

if (!$ret)
{
	if (mysql_errno() == 1062)
		error("Torrent already uploaded!");
	error("MySQL error: " . mysql_error());
}
$id = mysql_insert_id();

@query("DELETE FROM files WHERE torrent = $id");

foreach ($filelist as $file)
	query("INSERT INTO files (torrent, filename, size) VALUES ($id, ".sqlesc($file[0]).",".$file[1].")");

$fp = fopen("$torrent_dir/$id.torrent", "w");
if ($fp)
{
	fwrite($fp, benc($dict), strlen(benc($dict)));
	fclose($fp);
}

write_log("Torrent $id ($torrent) was uploaded by " . $CURUSER["username"]);


/* Email notifs */

$res = query("SELECT name FROM categories WHERE id=$catid") or sqlerr();
$arr = mysql_fetch_assoc($res);
$cat = $arr["name"];
$res = query("SELECT email FROM users WHERE enabled='yes' AND notifs LIKE '%[email]%' AND notifs LIKE '%[cat$catid]%'") or sqlerr();
$uploader = $CURUSER['username'];

$size = bytesize($totallen);
$description = ($html ? strip_tags($descr) : $descr);

$body = <<<EOD
A new torrent has been uploaded.

Name: $torrent
Size: $size
Category: $cat
Uploaded by: $uploader

Description
-------------------------------------------------------------------------------
$description
-------------------------------------------------------------------------------

You can use the URL below to download the torrent (you may have to login).

$SITEURL/details.php?id=$id&hit=1

-- 
$SITENAME
EOD;
$to = "";
$nmax = 100; // Max recipients per message
$nthis = 0;
$ntotal = 0;
$total = mysql_num_rows($res);
while ($arr = mysql_fetch_row($res))
{
  if ($nthis == 0)
    $to = $arr[0];
  else
    $to .= "," . $arr[0];
  ++$nthis;
  ++$ntotal;
  if ($nthis == $nmax || $ntotal == $total)
  {
    if (!mail("Multiple recipients <$SITEEMAIL>", "New torrent - $torrent", $body,
    "From: $SITEEMAIL\r\nBcc: $to", "-f$SITEEMAIL"))
	  error("There was a problem delivering the e-mail notifcations.\n" .
	    "Please let an administrator know about this error!\n");
    $nthis = 0;
  }
}

header("Location: $SITEURL/details.php?id=$id&uploaded=1$redown");

?>